use std::usize;

use egui::Vec2;
use enum_dispatch::enum_dispatch;
use normal_node::NormalNode;
use serde::{Deserialize, Serialize};

use crate::data::{InputData, NodeData, OutputData};

use super::value::Value;

mod normal_node;
mod root_node;
mod blackboard_out_ref_node;
mod blackboard_in_ref_node;
mod custom_data_node;
mod constant_node;
mod module_def_node;
mod module_ref_node;
mod include_constant_node;
mod include_custom_data_node;
mod include_module_ref_node;

#[derive(Clone, Serialize, Deserialize)]
#[enum_dispatch(NodeTrait)]
pub enum Node {
    /// 普通行为树节点
    Normal(normal_node::NormalNode),
    Root(root_node::RootNode),
    BlackboardOutRef(blackboard_out_ref_node::BlackboardOutRefNode),
    BlackboardInRef(blackboard_in_ref_node::BlackboardInRefNode),
    CustomData(custom_data_node::CustomDataNode),
    Constant(constant_node::ConstantNode),
    ModuleDef(module_def_node::ModuleDefNode),
    ModuleRef(module_ref_node::ModuleRefNode),
    IncludeConstant(include_constant_node::IncludeConstantNode),
    IncludeCustomData(include_custom_data_node::IncludeCustomDataNode),
    IncludeModuleRef(include_module_ref_node::IncludeModuleRefNode),
}

impl From<NodeData> for Node {
    fn from(value: NodeData) -> Self {
        Node::Normal(NormalNode::from(value))
    }
}

impl Node {
    pub fn new_root()->Self {
        Node::Root(root_node::RootNode::new())
    }
    
    pub fn new_blackboard_out_ref(value:Value)->Self {
        Node::BlackboardOutRef(blackboard_out_ref_node::BlackboardOutRefNode::new(value))
    }

    pub fn new_blackboard_in_ref(node_id:egui_snarl::NodeId, value:Value)->Self {
        Node::BlackboardInRef(blackboard_in_ref_node::BlackboardInRefNode::new(node_id, value))
    }

    pub fn new_custom_data(name:String, data:Value)->Self {
        Node::CustomData(custom_data_node::CustomDataNode::new(name, data))
    }

    pub fn new_constant(name:String, data:Value)->Self {
        Node::Constant(constant_node::ConstantNode::new(name, data))
    }

    pub fn new_module_def(name:String)->Self {
        Node::ModuleDef(module_def_node::ModuleDefNode::new(name))
    }

    pub fn new_module_ref(node_id:egui_snarl::NodeId)->Self {
        Node::ModuleRef(module_ref_node::ModuleRefNode::new(node_id))
    }

    pub fn new_include_constant(file:String, name:String, data:Value)->Self {
        Node::IncludeConstant(include_constant_node::IncludeConstantNode::new(file, name, data))
    }

    pub fn new_include_custom_data(file:String, name:String, data:Value)->Self {
        Node::IncludeCustomData(include_custom_data_node::IncludeCustomDataNode::new(file, name, data))
    }

    pub fn new_include_module_ref(file:String, ref_node_name:String)->Self {
        Node::IncludeModuleRef(include_module_ref_node::IncludeModuleRefNode::new(file, ref_node_name))
    }

}

#[enum_dispatch]
pub trait NodeTrait {
    fn name(&self) -> &str;
    fn ty(&self) -> &str;
    fn description(&self) -> Option<&str>;
    fn inputs(&self) -> &[Input];
    fn outputs(&self) -> &[Output];
    fn has_children(&self) -> bool;
    fn inputs_mut(&mut self) -> &mut Vec<Input>;
    fn outputs_mut(&mut self) -> &mut Vec<Output>;

    fn draw_name(&mut self, ui: &mut egui::Ui) -> bool {
        ui.label(self.name());
        false
    }

    /// None表示不限制
    fn children_count(&self) -> Option<usize> {
        None
    }

    fn get_input_info(&self, index:usize)->Option<&Input> {
        self.inputs().get(index)
    }

    fn get_input_info_mut(&mut self, index:usize)->Option<&mut Input> {
        self.inputs_mut().get_mut(index)
    }

    fn get_output_info(&self, index:usize)->Option<&Output> {
        self.outputs().get(index)
    }

    fn get_output_info_mut(&mut self, index:usize)->Option<&mut Output> {
        self.outputs_mut().get_mut(index)
    }

    fn can_copy(&self)->bool {
        true
    }

    fn can_delete(&self)->bool {
        true
    }
}

#[derive(Clone, Serialize, Deserialize)]
pub struct Input {
    pub name: String,
    pub description: Option<String>,
    pub value: Value,
}

impl From<InputData> for Input {
    fn from(value: InputData) -> Self {
        Self {
            name: value.name,
            description: value.description,
            value: value.value,
        }
    }
}

#[derive(Clone, Serialize, Deserialize)]
pub struct Output {
    pub name: String,
    pub description: Option<String>,
    pub value: Value,
}

impl From<OutputData> for Output {
    fn from(value: OutputData) -> Self {
        Self {
            name: value.name,
            description: value.description,
            value: value.value,
        }
    }
}

#[derive(Clone, Serialize, Deserialize)]
pub struct CopyNodeData {
    pub node:Node,
    pub position: Vec2,
}

#[derive(Clone, Serialize, Deserialize)]
pub struct CopyData {
    pub nodes: Vec<CopyNodeData>,
    pub wires: Vec<((usize, usize), (usize,usize))>,//(from_node, from_output), (to_node, to_input)
}

impl CopyData {
    pub fn new()->Self {
        Self {
            nodes: Vec::new(),
            wires: Vec::new(),
        }
    }
}
